package com.example.studyllm.config.exception;

import cn.hutool.core.util.StrUtil;
import com.example.studyllm.enums.ResultEnum;
import com.example.studyllm.vo.base.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.nio.file.AccessDeniedException;
import java.sql.SQLTransientConnectionException;
import java.util.List;

/**
 * @author wk
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @Value("${spring.profiles.active:dev}")
    private String active ;

	/**
     * 校验错误拦截处理
     *
     * @param exception 错误信息集合
     * @return 错误信息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result<String> validationBodyException(MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        String message = "";
        if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            if (errors != null) {
                errors.forEach(p -> {
                    FieldError fieldError = (FieldError) p;
                    log.error("Data check failure : object{" + fieldError.getObjectName() + "},field{" + fieldError.getField() +
                            "},errorMessage{" + fieldError.getDefaultMessage() + "}");

                });
                if (errors.size() > 0) {
                    FieldError fieldError = (FieldError) errors.get(0);
                    message = fieldError.getDefaultMessage();
                }
            }
        }
        return Result.error("".equals(message) ? "请填写正确信息" : message);
    }


    /**
     * 业务错误拦截
     * @param exception
     * @return
     */
    @ExceptionHandler(AccessDeniedException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result<String> accessDeniedException(AccessDeniedException exception){
        log.error("无权限访问：", exception);
        return Result.error(ResultEnum.UN_AUTH);
    }




    /**
     * 业务错误拦截
     * @param exception
     * @return
     */
    @ExceptionHandler(BusinessException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result<String> businessException(BusinessException exception){
        if(exception.getEnumType()!=null){
            return Result.error(exception.getEnumType().getDesc());
        }
    	log.error("捕获业务异常：", exception);
        if(StrUtil.isNotEmpty(exception.getMessage())){
            return Result.error(exception.getMessage());
        }
    	return Result.error();
    }



    /**
     * IllegalArgumentException错误拦截
     * @param exception
     * @return
     */
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result<String> illegalArgumentException(IllegalArgumentException exception){
        log.error("捕获业务异常：", exception);
        return Result.error(exception.getMessage());
    }





    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public Result<String> exception(Exception exception){
    	log.error("globalException：", exception);
    	if(active.equals("dev")){
    	    return Result.error();
        }
    	return Result.error(exception.getMessage());
    }
    

    /**
     * 拦截捕获 @RequestBody required=true 绑定请求参数异常
     *
     */
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result<String> validExceptionHandler(HttpMessageNotReadableException ex) {
        log.error("", ex);
        return Result.error(ResultEnum.BAD_REQUEST,ResultEnum.BAD_REQUEST.getDesc());
    }

    /**
     * 拦截捕获 @RequestBody required=true 绑定请求参数异常
     *
     */
    @ExceptionHandler(value = BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result<String> validExceptionHandler(BindException ex) {
        log.error("", ex);
        return Result.error(ResultEnum.BAD_REQUEST,ResultEnum.BAD_REQUEST.getDesc());
    }

    @ExceptionHandler(value = SQLTransientConnectionException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result<String> cannotGetJdbcConnectionExceptionHandle(SQLTransientConnectionException ex){
    	log.error("", ex);
     	return Result.error(ResultEnum.DB_CONNECT_ERROR);
    }

}
